import json
import os
import typing
from enum import Enum
from typing import List, Dict, Tuple
from copy import deepcopy

from docx import table as DocxTable
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Inches
import win32com.client as win32
from docx import Document
from docxcompose.composer import Composer

import StringUtils


# import pypandoc


def get_table_merges(table):
    """
    获取Word表格的合并范围信息

    参数:
        table: python-docx的Table对象

    返回:
        list: 包含合并范围信息的字典列表
              [{'cell': (row_idx, col_idx),
                'row_span': num,
                'col_span': num}]
    """
    merges = []
    for row_idx, row in enumerate(table.rows):
        for col_idx, cell in enumerate(row.cells):
            tc = cell._tc  # 获取底层XML元素
            tc_pr = tc.tcPr  # 单元格属性

            # 初始化合并信息
            merge_info = {
                'cell': (row_idx, col_idx),
                'row_span': 1,
                'col_span': 1
            }

            # 检查列合并(gridSpan)
            if tc_pr.gridSpan:
                merge_info['col_span'] = tc_pr.gridSpan.val

            # 检查行合并(vMerge)
            if tc_pr.vMerge:
                if tc_pr.vMerge.val == 'restart':
                    # 计算实际行跨度
                    span = 1
                    for r in range(row_idx + 1, len(table.rows)):
                        next_tc = table.rows[r].cells[col_idx]._tc
                        if next_tc.tcPr.vMerge and next_tc.tcPr.vMerge.val == 'continue':
                            span += 1
                        else:
                            break
                    merge_info['row_span'] = span

            # 如果是被合并的单元格则跳过
            if tc_pr.vMerge and tc_pr.vMerge.val == 'continue':
                continue

            # 只记录有合并的单元格
            if merge_info['row_span'] > 1 or merge_info['col_span'] > 1:
                merges.append(merge_info)

    return merges


class CellInfo:
    def __init__(self, cell: DocxTable._Cell, row_i: int, col_i: int):
        self.cell: DocxTable._Cell = cell
        self.row_i: int = row_i
        self.col_i: int = col_i

    __slots__ = ['cell', 'row_i', 'col_i']


# 非空cell 相同text的会合入
class MergedCells:
    def __init__(self):
        self.cells: typing.List[CellInfo] = []  # 每个实例初始化时创建自己的列表

    __slots__ = ['cells']

    def getRightLocation(self):
        min_row, min_col, max_row, max_col, _ = self.calculate_cell_range()
        return min_row, max_col + 1

    def getDownLocation(self):
        min_row, min_col, max_row, max_col, _ = self.calculate_cell_range()
        return max_row + 1, min_col

    def getThisLocation(self):
        min_row, min_col, max_row, max_col, _ = self.calculate_cell_range()
        return min_row, min_col

    def __str__(self):
        min_row, min_col, max_row, max_col, continued = self.calculate_cell_range(False)
        if (min_row != max_row) or (min_col != max_col):
            if continued:
                isCon = '连续'
            else:
                isCon = '不连续'
            return f"MergedRange start=({min_row},{min_col}) end=({max_row},{max_col}) === 合并, {isCon}"
        else:
            return f"MergedRange start=({min_row},{min_col}) end=({max_row},{max_col}) === 单"

    def calculate_cell_range(self, errorO=True):
        """
        计算CellInfo列表的行列范围并检查是否连续
         cell_info_list: List[CellInfo] CellInfo对象列表
        :return: 返回包含四个元素的元组 (min_row, min_col, max_row, max_col, is_continuous)
                 is_continuous表示行列是否连续
        """
        cell_info_list = self.cells
        if not cell_info_list:
            return 0, 0, 0, 0, True  # 空列表返回默认值

        # 初始化最小和最大值
        min_row = max_row = cell_info_list[0].row_i
        min_col = max_col = cell_info_list[0].col_i

        # 收集所有行列值用于连续性检查
        rows = set()
        cols = set()

        # 遍历所有CellInfo对象
        for cell_info in cell_info_list:
            # 更新行列范围f
            if cell_info.row_i < min_row:
                min_row = cell_info.row_i
            if cell_info.row_i > max_row:
                max_row = cell_info.row_i
            if cell_info.col_i < min_col:
                min_col = cell_info.col_i
            if cell_info.col_i > max_col:
                max_col = cell_info.col_i

            # 收集行列值
            rows.add(cell_info.row_i)
            cols.add(cell_info.col_i)

        # 检查行是否连续
        row_continuous = len(rows) == (max_row - min_row + 1) and sorted(rows) == list(range(min_row, max_row + 1))

        # 检查列是否连续
        col_continuous = len(cols) == (max_col - min_col + 1) and sorted(cols) == list(range(min_col, max_col + 1))

        if not (row_continuous and col_continuous):
            txt = cell_info_list[0].cell.text
            msg = f"所选范围非连续, 表格关键字：{txt}"
            print(msg)

            if errorO:
                raise IndexError(msg)

        return min_row, min_col, max_row, max_col, (row_continuous and col_continuous)


MatrixType = List[List[CellInfo]]

# cellDict 是字典，键是清理后的文本，值是 MergedCells 对象
CellDictType = Dict[str, MergedCells]


# return:
#   cellDict: {clean_text -> MergedCells }
#   matrix: 由横纵坐标组成的二维矩阵，值为 clean_text
def resolveTable(table) -> Tuple[CellDictType, MatrixType]:
    if not table:
        raise Exception("resolveTableExample no arg")

    cellDict: CellDictType = {}
    matrix: MatrixType = []

    for row_index, row in enumerate(table.rows):
        matrixR = []
        for col_index, cell in enumerate(row.cells):
            clean_text = cell.text.strip()
            cellInfo = CellInfo(cell, row_index, col_index)
            matrixR.append(cellInfo)
            if StringUtils.is_string_non_empty_and_not_only_whitespace(clean_text):
                if clean_text in cellDict:
                    cellEle = cellDict[clean_text]
                    cellEle.cells.append(cellInfo)
                else:
                    cellEle = MergedCells()
                    cellEle.cells.append(cellInfo)
                    cellDict[clean_text] = cellEle

        matrix.append(matrixR)

    return cellDict, matrix


class TableInfo:
    def __init__(self, table: DocxTable, cellDict: CellDictType, matrix: MatrixType):
        self.table: DocxTable = table
        self.cellDict: CellDictType = cellDict
        self.matrix: MatrixType = matrix

    __slots__ = ['table', 'cellDict', 'matrix']


kSkpi = '工序号'


class TableE(Enum):
    # 表格枚举
    kModel = '机型'
    kRev = '更改记录'
    kStandNInfo = '所需工艺规范'
    kToolEquip = '所需工装'
    kPart = '所需零组件'
    kSket = '参考草图'
    # kSeqAA = '局方意见'
    kSeqEg = 'EXAMPLES'
    kCatalog = '工程更改'


class ETableAR(Enum):
    kModel = '机'
    kSeq = '工序号'
    kPart = '所需零组件'
    kRef = '引用'
    kEng = '工程'


class ParentTable:
    def __init__(self, tableInfo: TableInfo, tableE: Enum):
        self.tableInfo: TableInfo = tableInfo
        self.tableTag: str = tableE.value
        tmpDict = {}
        for k, v in self.tableInfo.cellDict.items():
            cleaned_text = StringUtils.extract_english_letters(k)
            tmpDict[cleaned_text] = v

        for k, v in tmpDict.items():
            self.tableInfo.cellDict[k] = v

    def printCells(self):
        print(f"=============== table {self.tableTag}: ===============")
        cellDict = self.tableInfo.cellDict
        for cTxt, mergedCells in cellDict.items():
            cleaned_text = cTxt.replace('\n', '').replace('\r', '')

            print(f"{cleaned_text} ====> {mergedCells}")
        print(f"*************** table {self.tableTag}: ***************")
        print()

    def printMatrix(self):
        m = self.tableInfo.matrix
        print(f"matrix rows: {len(m)}")
        print(f"matrix columns: {len(m[0])}")

    def setSingleRightOf(self, cellKey: str, txtToWrite: str) -> CellInfo:
        cell = self.tableInfo.cellDict[cellKey]
        r, c = cell.getRightLocation()
        targetCellInfo = self.tableInfo.matrix[r][c]
        _write_cell(targetCellInfo.cell, txtToWrite)

    def setSingleBelowOf(self, cellKey: str, txtToWrite: str) -> CellInfo:
        targetCellInfo = self.getSingleBelow(cellKey)
        _write_cell(targetCellInfo.cell, txtToWrite)

    def getSingleBelow(self, cellKey: str) -> CellInfo:
        cell = self.tableInfo.cellDict[cellKey]
        r, c = cell.getDownLocation()
        targetCellInfo = self.tableInfo.matrix[r][c]
        return targetCellInfo

    def getSingle(self, cellKey: str) -> CellInfo:
        cell = self.tableInfo.cellDict[cellKey]
        r, c = cell.getThisLocation()
        targetCellInfo = self.tableInfo.matrix[r][c]
        return targetCellInfo


# 机型 MODEL 表
class TableModel(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.curIndex = 3
        self.maxIndex = 11

    __slots__ = ['curIndex', 'maxIndex']

    def setModel(self, model: str):
        self.setSingleRightOf('MODEL', model)

    def setPartNum(self, partNum: str):
        self.setSingleRightOf('PARTNUMBER', partNum)

    def setProgramNO(self, progNum: str):
        self.setSingleRightOf('ProgramNO', progNum)

    def setEff(self, eff: str):
        self.setSingleRightOf('EFF', eff)

    def setInterchange(self, interchange: str):
        self.setSingleRightOf('CATEGORYOFINTERCHANGEABILITY', interchange)

    def setCompiled(self, content: str):
        self.setSingleBelowOf('COMPILEDBY', content)

    def setCHECKEDBY(self, content: str):
        self.setSingleBelowOf('CHECKEDBY', content)

    def setQA(self, content: str):
        self.setSingleBelowOf('QA', content)

    def setAPPROVEDBY(self, content: str):
        self.setSingleBelowOf('APPROVEDBY', content)

    def setSeal(self, content: str):
        single = self.getSingle('SEAL')
        text = single.cell.text
        print("SEAL =====", text)
        _add_two_paragraphs_to_cell(single.cell, content)

    def addItem(self, seq: str, no: str, sheet: str, eo1: str):
        if self.curIndex > self.maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, no)
        _write_cell(row[5].cell, sheet)
        _write_cell(row[8].cell, eo1)

        self.curIndex += 1


class TableSketch(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.imgCnt = 0

    __slots__ = ['imgCnt']

    def setSketchPic(self, imgPath: str):
        cellInfo = self.getSingleBelow('SKETCHFORREFERENCE')
        cellInfo.cell.paragraphs[0].add_run().add_picture(imgPath, width=Inches(2), height=Inches(1))

    def addSketchPic(self, imgPath: str):
        cellInfo = self.getSingleBelow('SKETCHFORREFERENCE')
        if self.imgCnt >= 1:
            cellInfo.cell.add_paragraph()

        if os.path.exists(imgPath):
            p = cellInfo.cell.paragraphs[self.imgCnt]  # 获取段落
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER  # 让段落居中
            run = p.add_run()
            run.add_picture(imgPath, width=Inches(7.08))  # 插入图片
            self.imgCnt += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 1
            if row_idx < 1:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(8):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


class TablePart(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.curIndex = 2
        self.maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ['curIndex', 'maxIndex']

    def addItem(self, seq: str, no: str, name: str, spec: str, typ: str, qty: str, nex: str, note: str):
        if self.curIndex > self.maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, name)
        _write_cell(row[3].cell, spec)
        _write_cell(row[4].cell, typ)
        _write_cell(row[5].cell, f"{qty}")
        _write_cell(row[6].cell, nex)
        _write_cell(row[7].cell, note)
        self.curIndex += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2
            if row_idx < 2:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(8):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


class TableSeq(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.curIndex = 1
        self.maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ['curIndex', 'maxIndex']

    def addItem(self, seq: str, process: str, instructions: str, tooling: str, eg: str, key: str, tagPath: str):
        if self.curIndex > self.maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, process)
        _write_cell_Instruction(row[2].cell, instructions)
        _write_cell(row[3].cell, tooling)
        _write_cell(row[4].cell, eg)

        if self.shouldPutTag(key):
            row[0].cell.paragraphs[0].add_run().add_picture(tagPath)

        self.curIndex += 1

    def addRows(self, ls: [], tagPngPath: str):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 1
            if row_idx < 1:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(5):
                if col_idx == 2:
                    _write_cell_Instruction(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])
                else:
                    _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])
            if self.shouldPutTag(ls[data_idx][5]):
                self.tableInfo.table.rows[row_idx].cells[0].paragraphs[0].add_run().add_picture(tagPngPath)

    # tag 非空就可以
    def shouldPutTag(self, tag: str) -> bool:
        return len(tag) > 0


# 资源表
class TableTooling(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.curIndex = 2
        self.maxIndex = len(tableInfo.matrix) - 1
        self.seq = 1

    __slots__ = ['curIndex', 'maxIndex', 'seq']

    def addItem(self, no: str, name: str, spec1: str, spec2: str, spec3: str, spec4: str):
        if self.curIndex > self.maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndex]
        _write_cell(row[0].cell, f"{self.seq}")
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, name)
        _write_cell(row[3].cell, spec1)
        _write_cell(row[4].cell, spec2)
        _write_cell(row[5].cell, spec3)
        _write_cell(row[6].cell, spec4)

        self.curIndex += 1
        self.seq += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2

            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(7):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


# 文档表 kStandNInfo
class TableStandNInfo(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.curIndex = 2
        self.maxIndex = 14
        self.seq = 1
        self.seqUnder = 1
        self.curIndexUnder = 17
        self.maxIndexUnder = 20

    __slots__ = ['curIndex', 'maxIndex', 'seq', 'seqUnder', 'curIndexUnder', 'maxIndexUnder']

    def addItem(self, no: str, name: str):
        if self.curIndex > self.maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndex]
        _write_cell(row[0].cell, f"{self.seq}")
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, name)

        self.curIndex += 1
        self.seq += 1

    def addItemUnder(self, no: str, name: str):
        if self.curIndexUnder > self.maxIndexUnder:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndexUnder]
        _write_cell(row[0].cell, f"{self.seqUnder}")
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, name)

        self.curIndexUnder += 1
        self.seqUnder += 1

    def addRowsUnder(self, ls: []):
        for data_idx in range(len(ls), ):
            row_idx = data_idx + 17

            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(3):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


# AO 更改记录表
class TableRevision(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self.curIndex = 2
        self.maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ['curIndex', 'maxIndex']

    def addItem(self, rev: str, date: str, effect: str, change: str, source: str, revised: str, appr: str, buyer: str):
        if self.curIndex > self.maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self.curIndex]
        _write_cell(row[0].cell, f"{rev}")
        _write_cell(row[1].cell, date)
        _write_cell(row[2].cell, effect)
        _write_cell(row[3].cell, change)
        _write_cell(row[4].cell, source)
        _write_cell(row[5].cell, revised)
        _write_cell(row[6].cell, appr)
        _write_cell(row[7].cell, buyer)

        self.curIndex += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2
            if row_idx < 2:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(8):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


class TableCatalog(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: TableE):
        super().__init__(tableInfo, tableE)
        self._curIndex = 2
        self._maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ["_curIndex", "_maxIndex"]

    def addItem(self, seq: str, no: str, ver: str, name: str, quan: str, changeNo: str, processNo: str,
                processVer: str):
        if self._curIndex > self._maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self._curIndex]
        _write_cell(row[0].cell, f"{seq}")
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, ver)
        _write_cell(row[3].cell, name)
        _write_cell(row[4].cell, quan)
        _write_cell(row[5].cell, changeNo)
        _write_cell(row[6].cell, processNo)
        _write_cell(row[7].cell, processVer)

        self._curIndex += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2
            if row_idx < 2:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(8):
                if col_idx == 2:
                    _write_cell_left(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])
                else:
                    _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


class TableARModel(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: ETableAR):
        super().__init__(tableInfo, tableE)

    __slots__ = []

    def fillModel(self, model: str):
        self.setSingleRightOf('MODEL', model)

    def fillProgName(self, prog: str):
        self.setSingleRightOf('PROGRAMNAME', prog)

    def fillKI(self, ki: str):
        self.setSingleRightOf('keyimportantprocesses', ki)


class TableARSeq(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: ETableAR):
        super().__init__(tableInfo, tableE)
        self._curIndex = 2
        self._maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ["_curIndex", "_maxIndex"]

    def addItem(self, seq: str, process: str, record: str, op: str, qty: str, inspec: str, nQty: str, nNo: str,
                note: str, key: str, tagPath: str):
        if self._curIndex > self._maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self._curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, process)
        _write_cell_Instruction(row[2].cell, record)
        _write_cell(row[3].cell, op)
        _write_cell(row[4].cell, qty)
        _write_cell(row[5].cell, inspec)
        _write_cell(row[6].cell, nQty)
        _write_cell(row[7].cell, nNo)
        _write_cell(row[8].cell, note)

        if self.shouldPutTag(key):
            row[0].cell.paragraphs[0].add_run().add_picture(tagPath)

        self._curIndex += 1

    def addRows(self, ls: typing.List, tagPngPath: str):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2
            if row_idx < 2:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(9):
                if col_idx == 2:
                    _write_cell_Instruction(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])
                else:
                    _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])

            if self.shouldPutTag(ls[data_idx][-1]):
                self.tableInfo.table.rows[row_idx].cells[0].paragraphs[0].add_run().add_picture(tagPngPath)

    # tag 非空就可以
    def shouldPutTag(self, tag: str) -> bool:
        return len(tag) > 0
    # def addRows(self, ls: typing.List):
    #     import logging
    #     logging.basicConfig(level=logging.DEBUG)
    #
    #     for data_idx in range(len(ls)):
    #         row_idx = data_idx + 2
    #         if row_idx < 2:
    #             continue
    #
    #         # 记录当前处理的行和数据索引
    #         logging.debug(f"Processing data_idx: {data_idx}, row_idx: {row_idx}")
    #
    #         # 如果表格行数不够，添加新行
    #         current_row_count = len(self.tableInfo.table.rows)
    #         logging.debug(f"Current table row count: {current_row_count}")
    #
    #         if row_idx >= current_row_count:
    #             logging.debug(f"Adding new row, current count: {current_row_count}")
    #             self.tableInfo.table.add_row()
    #             current_row_count = len(self.tableInfo.table.rows)
    #             logging.debug(f"New row count: {current_row_count}")
    #
    #         # 检查行索引是否有效
    #         if row_idx >= current_row_count:
    #             logging.error(f"Row index {row_idx} out of range (max {current_row_count - 1})")
    #             continue
    #
    #         # 写入数据
    #         current_col_count = len(self.tableInfo.table.rows[row_idx].cells)
    #         logging.debug(f"Current column count for row {row_idx}: {current_col_count}")
    #
    #         for col_idx in range(9):
    #             # 检查列索引是否有效
    #             if col_idx >= current_col_count:
    #                 logging.error(
    #                     f"Column index {col_idx} out of range (max {current_col_count - 1}) for row {row_idx}")
    #                 continue
    #
    #             try:
    #                 logging.debug(f"Writing to cell at row {row_idx}, column {col_idx}")
    #                 _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])
    #             except IndexError as e:
    #                 logging.error(f"IndexError at data_idx={data_idx}, row_idx={row_idx}, col_idx={col_idx}")
    #                 logging.error(
    #                     f"Table dimensions: rows={len(self.tableInfo.table.rows)}, columns={len(self.tableInfo.table.rows[row_idx].cells) if row_idx < len(self.tableInfo.table.rows) else 'N/A'}")
    #                 logging.error(
    #                     f"Data dimensions: len(ls)={len(ls)}, len(ls[data_idx])={len(ls[data_idx]) if data_idx < len(ls) else 'N/A'}")
    #                 raise


class TableARPart(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: ETableAR):
        super().__init__(tableInfo, tableE)
        self._curIndex = 2
        self._maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ["_curIndex", "_maxIndex"]

    def addItem(self, seq: str, no: str, name: str, rev: str, typ: str, qty: str, traNo: str, note: str):
        if self._curIndex > self._maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self._curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, name)
        _write_cell(row[3].cell, rev)
        _write_cell(row[4].cell, typ)
        _write_cell(row[5].cell, qty)
        _write_cell(row[6].cell, traNo)
        _write_cell(row[7].cell, note)

        self._curIndex += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2
            if row_idx < 2:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(8):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


class TableARRef(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: ETableAR):
        super().__init__(tableInfo, tableE)
        self._curIndex = 2
        self._maxIndex = len(tableInfo.matrix) - 2

    __slots__ = ["_curIndex", "_maxIndex"]

    def addItem(self, seq: str, no: str, name: str, iss: str, final: str, ana: str):
        if self._curIndex > self._maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self._curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, name)
        _write_cell(row[3].cell, iss)
        _write_cell(row[4].cell, final)
        _write_cell(row[5].cell, ana)

        self._curIndex += 1

    def fillNameAndDate(self, name: str, date: str):
        m = self.tableInfo.matrix
        cell = m[15][0].cell

        full_text = "".join(run.text for run in cell.paragraphs[0].runs)

        newT = _fill_text(full_text, "工艺员签字：", name)
        newT = _fill_text(newT, "日期：", date)

        cell.paragraphs[0].clear()
        p = cell.paragraphs[0]
        p.add_run(newT)
        print(newT)


def _fill_text(original, marker, new_content):
    start = original.index(marker) + len(marker)
    # 计算后续空白长度（确保新内容不超过空白区域）
    space_count = 0
    while start + space_count < len(original) and original[start + space_count] in " 　":
        space_count += 1
    # 替换空白（保留超出部分的原始内容）
    return original[:start] + new_content.ljust(space_count) + original[start + space_count:]


class TableAREngChange(ParentTable):
    def __init__(self, tableInfo: TableInfo, tableE: ETableAR):
        super().__init__(tableInfo, tableE)
        self._curIndex = 2
        self._maxIndex = len(tableInfo.matrix) - 1

    __slots__ = ["_curIndex", "_maxIndex"]

    def addItem(self, seq: str, no: str, ver: str, name: str, quant: str, changeNo: str, procNo: str, procVer: str):
        if self._curIndex > self._maxIndex:
            return

        m = self.tableInfo.matrix
        row = m[self._curIndex]
        _write_cell(row[0].cell, seq)
        _write_cell(row[1].cell, no)
        _write_cell(row[2].cell, ver)
        _write_cell(row[3].cell, name)
        _write_cell(row[4].cell, quant)
        _write_cell(row[5].cell, changeNo)
        _write_cell(row[6].cell, procNo)
        _write_cell(row[7].cell, procVer)

        self._curIndex += 1

    def addRows(self, ls: []):
        for data_idx in range(len(ls)):
            row_idx = data_idx + 2
            if row_idx < 2:
                continue
            # 如果表格行数不够，添加新行
            if row_idx >= len(self.tableInfo.table.rows):
                self.tableInfo.table.add_row()
            # 写入数据
            for col_idx in range(8):
                _write_cell(self.tableInfo.table.rows[row_idx].cells[col_idx], ls[data_idx][col_idx])


def _write_cell(cell: DocxTable._Cell, text: str) -> None:
    """写入单元格文本并设置居中

    Args:
        cell (Cell): docx.table.Cell 对象
        text (str): 要写入的文本
    """
    cell.text = text
    if cell.paragraphs:  # 检查是否有段落（避免空单元格报错）
        cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER


def _write_cell_left(cell: DocxTable._Cell, text: str) -> None:
    """写入单元格文本并设置居中

    Args:
        cell (Cell): docx.table.Cell 对象
        text (str): 要写入的文本
    """
    cell.text = text
    if cell.paragraphs:  # 检查是否有段落（避免空单元格报错）
        cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.LEFT


def _write_cell_Instruction(cell: DocxTable._Cell, json_str: str) -> None:
    _clear_cell(cell)

    try:
        data = json.loads(json_str)
        # 清空单元格原有内容

        for item in data:
            if item["type"] == "table":
                _write_table(cell, item["data"])
            elif item["type"] == "p":
                _write_paragraph(cell, item["content"])
            else:
                raise ValueError(f"Unknown type: {item['type']}")
    except json.JSONDecodeError as e:
        _write_cell_left(cell, json_str)


def _clear_cell(cell):
    for paragraph in cell.paragraphs:
        p = paragraph._element
        p.getparent().remove(p)


def _write_table(cell: DocxTable._Cell, table_data: Dict) -> None:
    """在单元格内写入嵌套表格"""
    # 在单元格内创建嵌套表格
    table = cell.add_table(rows=table_data["max_rows"], cols=table_data["max_cols"])

    _set_table_borders(table)

    # 填充表格数据
    for entry in table_data["data"]:
        row = entry["row"] - 1  # 转换为 0-based 索引
        col = entry["col"] - 1
        table.cell(row, col).text = str(entry["value"])

    _set_table_total_width(table, 25)


def _set_table_total_width(table, width_cm):
    """通过XML设置表格整体宽度"""
    tbl = table._tbl
    tblPr = tbl.tblPr

    # 创建或修改tblW元素
    tblW = OxmlElement('w:tblW')
    tblW.set(qn('w:w'), str(int(width_cm * 360)))  # 厘米转Twips单位
    tblW.set(qn('w:type'), 'dxa')  # 固定宽度模式

    if tblPr is None:
        tblPr = OxmlElement('w:tblPr')
        tbl.insert(0, tblPr)
    tblPr.append(tblW)


def _set_table_borders(table: DocxTable) -> None:
    """设置表格所有边框为单实线"""
    tbl = table._tbl
    tblBorders = OxmlElement('w:tblBorders')

    # 为所有边框类型设置单实线
    for border_name in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'):
        border = OxmlElement(f'w:{border_name}')
        border.set(qn('w:val'), 'single')
        border.set(qn('w:sz'), '4')
        border.set(qn('w:space'), '0')
        border.set(qn('w:color'), 'auto')
        tblBorders.append(border)

    tbl.tblPr.append(tblBorders)


def _write_paragraph(cell: DocxTable._Cell, content: str) -> None:
    """在单元格内写入段落文本"""
    paragraph = cell.add_paragraph(content)
    paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT


def _add_two_paragraphs_to_cell(cell, text1):
    for paragraph in cell.paragraphs:
        p = paragraph._element
        p.getparent().remove(p)

        # 删除所有嵌套表格
    for table in cell.tables:
        tbl = table._element
        tbl.getparent().remove(tbl)

    # 清除单元格原有内容（可选）
    # for paragraph in cell.paragraphs:
    #     paragraph.clear()

    # 添加第一段文字（左对齐，靠近顶端）
    txt = text1
    for i in range(16):
        if i == 7:
            txt += '\n                    印章标识  SEAL'
        else:
            txt += '\n'
    p1 = cell.add_paragraph(f'{txt}')
    p1.alignment = WD_ALIGN_PARAGRAPH.LEFT

    # 设置第一段文字的字体和间距（可选）
    # for run in p1.runs:
    #     run.font.size = Pt(12)

    # 添加第二段文字（居中对齐，垂直居中）
    # p2 = cell.add_paragraph(text2)
    # p2.alignment = WD_ALIGN_PARAGRAPH.CENTER

    # 设置第二段文字的字体和间距（可选）
    # for run in p2.runs:
    #     run.font.size = Pt(12)

    # 设置整个单元格的垂直对齐方式为居中
    # cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER


def merge_docs_no_div(output, *files):
    word = win32.Dispatch("Word.Application")
    word.Visible = False
    doc = word.Documents.Open(files[0])
    for f in files[1:]:
        doc.Application.Selection.EndKey(Unit=6)  # 跳到末尾
        doc.Application.Selection.InsertFile(f)
    doc.SaveAs(output)
    doc.Close()
    word.Quit()


def merge_docs(output, *files):
    word = win32.Dispatch("Word.Application")
    word.Visible = False

    doc = word.Documents.Open(files[0])
    sel = word.Selection

    # 从 Word 枚举中取常量
    wdStory = word.WdUnits.wdStory
    wdPageBreak = word.WdBreakType.wdPageBreak

    for f in files[1:]:
        sel.EndKey(Unit=wdStory)
        sel.InsertBreak(Type=wdPageBreak)
        sel.InsertFile(f, ConfirmConversions=False, Link=False, Attachment=False)

    doc.SaveAs(output)
    doc.Close(False)
    word.Quit()


if __name__ == "__main__":
    file1: str = r"C:\\Users\\Administrator\\Desktop\\F010203-02装配制造记录Rev.8.docx"
    file2: str = r"C:\\Users\\Administrator\\Desktop\\F010203-01装配大纲Rev.8.docx"

    out = r"C:\\Users\\Administrator\\Desktop\\merged.docx"

    merge_docs(
        out,
        file1,
        file2
    )

# if __name__ == '__main__':
#     file1: str = "C:\\Users\\Administrator\\Desktop\\F010203-02装配制造记录Rev.8.docx"
#     file2: str = "C:\\Users\\Administrator\\Desktop\\F010203-01装配大纲Rev.8.docx"
#
#     master = Document(file1)
#     doc2 = Document(file2)
#
#     # 把 file2 的第一个节配置拿出来（包含横向/纵向、页边距等）
#     sectPr_doc2 = doc2.sections[0]._sectPr
#
#     # 在 master 末尾插入一个“跟 file2 一样配置”的节
#     insert_section_with_pr(master, sectPr_doc2)
#
#     composer = Composer(master)
#
#     composer.append(Document(file2))
#     composer.save("C:\\Users\\Administrator\\Desktop\\merged.docx")
